package com.example.blue_classic_plus.ble;

import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattServer;
import android.bluetooth.BluetoothGattServerCallback;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.le.AdvertiseCallback;
import android.bluetooth.le.AdvertiseData;
import android.bluetooth.le.AdvertiseSettings;
import android.bluetooth.le.BluetoothLeAdvertiser;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.os.ParcelUuid;
import android.text.TextUtils;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@SuppressLint("NewApi")
public class BleServer {

    private final String ServerStateType = "serverState";

    private BluetoothManager bluetoothManager;
    private BluetoothLeAdvertiser advertiser;
    private AdvertiseCallback advertiseCallback;

    BluetoothGattServer gattServer;
    BluetoothGattService service;
    BluetoothGattCharacteristic characteristic;

    private String uuid;

    Handler handler;

    public boolean serverListening = false;


    public BleServer(Context context, String uuid, String name, Handler handler) {
        this.uuid = uuid;
        this.handler = handler;
        bluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
        BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();
        bluetoothAdapter.setName(name);
        advertiser = bluetoothAdapter.getBluetoothLeAdvertiser();
    }


    public void startAdvertising(Context context) {
        if (advertiser != null) {

            //广播设置(必须)
            AdvertiseSettings settings = new AdvertiseSettings.Builder()
                    .setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY) //广播模式: 低功耗,平衡,低延迟
                    .setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH) //发射功率级别: 极低,低,中,高
                    .setConnectable(true) //能否连接,广播分为可连接广播和不可连接广播
                    .setTimeout(0)
                    .build();

            //广播数据(必须，广播启动就会发送)
            AdvertiseData data = new AdvertiseData.Builder()
                    .setIncludeDeviceName(true) //包含蓝牙名称
                    .setIncludeTxPowerLevel(true) //包含发射功率级别
                    //.addManufacturerData(1, new byte[]{23, 33}) //设备厂商数据，自定义
                    .build();

            //扫描响应数据(可选，当客户端扫描时才发送)
            AdvertiseData scanResponseData = new AdvertiseData.Builder()
                    //.addManufacturerData(2, new byte[]{66, 66}) //设备厂商数据，自定义
                    .addServiceUuid(new ParcelUuid(UUID.fromString(uuid))) //服务UUID
                    //.addServiceData(new ParcelUuid(UUID_SERVICE), new byte[]{2}) //服务数据，自定义
//                  //.setIncludeTxPowerLevel(true)
                    .build();

            ///广播成功失败的回调
            advertiseCallback = new AdvertiseCallback() {
                @Override
                public void onStartSuccess(AdvertiseSettings settingsInEffect) {
                    super.onStartSuccess(settingsInEffect);
                    // 广播成功
                    serverListening = true;
                    toFlutterType(ServerStateType, 7, "蓝牙服务端开启监听中");
                }

                @Override
                public void onStartFailure(int errorCode) {
                    super.onStartFailure(errorCode);
                    // 广播失败，处理错误
                    serverListening = false;
                    toFlutterType(ServerStateType, 6, "蓝牙服务端开启出错");
                }
            };


            ///服务
            service = new BluetoothGattService(
                    UUID.fromString(uuid),
                    BluetoothGattService.SERVICE_TYPE_PRIMARY
            );

            ///特征
            characteristic = new BluetoothGattCharacteristic(
                    UUID.fromString(uuid),
                    BluetoothGattCharacteristic.PROPERTY_READ | BluetoothGattCharacteristic.PROPERTY_WRITE | BluetoothGattCharacteristic.PROPERTY_NOTIFY,
                    BluetoothGattCharacteristic.PERMISSION_READ | BluetoothGattCharacteristic.PERMISSION_WRITE
            );

            ///描述符 这个UUID是写死的
            BluetoothGattDescriptor descriptor = new BluetoothGattDescriptor(
                    UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"),
                    BluetoothGattDescriptor.PERMISSION_READ | BluetoothGattDescriptor.PERMISSION_WRITE
            );
            descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);

            characteristic.addDescriptor(descriptor);
            service.addCharacteristic(characteristic);
            gattServer = bluetoothManager.openGattServer(context, gattServerCallback);
            gattServer.addService(service);

            advertiser.startAdvertising(settings, data, scanResponseData, advertiseCallback);
        } else {
            toFlutterType(ServerStateType, 2, "设备 不支持BLE");
        }
    }

    ///关闭服务端
    public void stopServer() {
        if (advertiser != null) {
            advertiser.stopAdvertising(advertiseCallback);
        }
        if (gattServer != null) {
            //gattServer.removeService(service);
            gattServer.close();
        }
        serverListening = false;
    }

    ///GATT 服务器回调
    BluetoothGattServerCallback gattServerCallback = new BluetoothGattServerCallback() {

        ///当连接状态发生改变时调用，可以用于处理连接和断开连接的事件
        @Override
        public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
            super.onConnectionStateChange(device, status, newState);
            if (newState == BluetoothProfile.STATE_CONNECTED && status == BluetoothGatt.GATT_SUCCESS) {
                // 连接成功
                // 执行连接成功后的操作
                toFlutterType(ServerStateType, 8, "客户端连接成功");
            } else {
                // 连接失败
                // 执行连接失败后的操作
                toFlutterType(ServerStateType, 10, "客户端断开连接");
            }

        }

        ///GATT服务被添加到服务器时调用，可以用于处理服务添加成功或失败的情况。
        @Override
        public void onServiceAdded(int status, BluetoothGattService service) {
            super.onServiceAdded(status, service);
            System.out.println("gattServer：服务添加成功");
        }

        ///当有读取特征值的请求时调用，可以用于处理读取请求并返回相应的特征值数据。
        @Override
        public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) {
            super.onCharacteristicReadRequest(device, requestId, offset, characteristic);
            System.out.println("gattServer onCharacteristicReadRequest");
        }


        ///当有写入特征值的请求时调用，可以用于处理写入请求并更新特征值数据。
        @Override
        public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
            super.onCharacteristicWriteRequest(device, requestId, characteristic, preparedWrite, responseNeeded, offset, value);
            System.out.println("gattServer onCharacteristicWriteRequest");
        }

        ///当有写入描述符的请求时调用，可以用于处理写入请求并更新描述符数据。
        @Override
        public void onDescriptorWriteRequest(BluetoothDevice device, int requestId, BluetoothGattDescriptor descriptor, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
            super.onDescriptorWriteRequest(device, requestId, descriptor, preparedWrite, responseNeeded, offset, value);
            System.out.println("gattServer onDescriptorWriteRequest");

            // 1. 检查是否需要响应。如果需要，那么你应该在处理完请求后发送一个响应给客户端。
            if (responseNeeded) {
                // 2. 使用方法 mGattServer.sendResponse() 向客户端发送响应。
                gattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, value);
            }

            // 3. 在这里处理你的写入请求。例如，你可以将值存储在某个地方，或者改变你的设备的行为。

        }

        ///当有读取描述符的请求时调用，可以用于处理读取请求并返回相应的描述符数据。
        @Override
        public void onDescriptorReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattDescriptor descriptor) {
            super.onDescriptorReadRequest(device, requestId, offset, descriptor);
            System.out.println("gattServer onDescriptorReadRequest");
        }

        ///当通知已经成功发送到远程设备时
        @Override
        public void onNotificationSent(BluetoothDevice device, int status) {
            super.onNotificationSent(device, status);
//            if (status == BluetoothGatt.GATT_SUCCESS) {
//                System.out.println("gattServer： 消息发送成功");
//            } else {
//                System.out.println("gattServer： 消息发送失败");
//            }
        }

        ///通知应用程序当设备的MTU（最大传输单元）发生变化时
        ///mtu：表示新的MTU值
        ///应用程序可以获取到MTU的变化情况，并根据需要进行相应的处理，例如根据新的MTU值重新调整数据传输的方式，以提高通信效率和性能。
        @Override
        public void onMtuChanged(BluetoothDevice device, int mtu) {
            super.onMtuChanged(device, mtu);
            System.out.println("gattServer onMtuChanged mtu =" + mtu);
        }

        ///当远程设备请求执行已经准备好的写入操作时
        @Override
        public void onExecuteWrite(BluetoothDevice device, int requestId, boolean execute) {
            super.onExecuteWrite(device, requestId, execute);
            System.out.println("gattServer onDescriptorWriteRequest");
        }
    };

    public void broadcastData(String msg) {
        if (bluetoothManager == null) return;

        Thread sendThread = new Thread(() -> {
            try {
                // 获取已连接的设备列表
                List<BluetoothDevice> devices = bluetoothManager.getConnectedDevices(BluetoothProfile.GATT);
                for (BluetoothDevice device : devices) {
                    // 确保设备已经连接
                    if (bluetoothManager.getConnectionState(device, BluetoothProfile.GATT) == BluetoothProfile.STATE_CONNECTED) {
                        // 获取Characteristic

                        //BluetoothGattCharacteristic characteristic = service.getCharacteristic(UUID.fromString("0000xxxx-0000-1000-8000-00805f9b34fb"));

                        // 设置Characteristic的值
                        characteristic.setValue(msg.getBytes(StandardCharsets.UTF_8));

                        // 通知已连接的设备Characteristic的值已经改变
                        gattServer.notifyCharacteristicChanged(device, characteristic, false);
                    }
                }
            } catch (Exception e) {
                System.out.println("消息发送失败:" + e);
            }
        });
        sendThread.start();
    }


    ///发送消息给Flutter
    public void toFlutterType(String type, int code, String msg) {
        Map<String, Object> map = new HashMap<>();
        map.put("type", type);
        map.put("code", code);
        if (!TextUtils.isEmpty(msg)) {
            map.put("msg", msg);
        }
        Message message = this.handler.obtainMessage(0, map);
        this.handler.sendMessage(message);
    }

}
